/**
 * Wihidum - Efficient Broker Hierarchy for Publish Subscribe Middleware
 *
 * License      :   Apache License 2.0
 * Home Page    :   http://code.google.com/p/wihidum/
 * Mailing List :   wihidum@googlegroups.com
 */

package lk.mrt.cse.wihidum.processor;

import org.apache.axiom.soap.SOAPEnvelope;
import org.apache.axiom.soap.SOAPFactory;
import org.apache.axiom.soap.SOAPBody;
import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMException;
import org.apache.axiom.om.OMNamespace;
import org.apache.log4j.Logger;
import org.apache.axis2.client.ServiceClient;
import org.apache.axis2.client.Options;
import org.apache.axis2.client.OperationClient;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.AxisFault;

import javax.xml.namespace.QName;

import lk.mrt.cse.wihidum.storage.ClientList;
import lk.mrt.cse.wihidum.storage.Broker;
import lk.mrt.cse.wihidum.storage.BrokerList;
import lk.mrt.cse.wihidum.util.WihidumConstants;
import lk.mrt.cse.wihidum.util.WSEventingConstants;

import java.util.ArrayList;

public class RemoveBrokerProcessor implements Processor{

    private static final Logger logger = Logger.getLogger(RemoveBrokerProcessor.class);

    public SOAPEnvelope processMessage(SOAPEnvelope requestEnvelope) {

        try {
            SOAPFactory factory = OMAbstractFactory.getSOAP11Factory();
            SOAPEnvelope responseEnvelop = factory.getDefaultEnvelope();

            OMElement addressElement = requestEnvelope.getBody()
                    .getFirstChildWithName(new QName("BrokerDetails"))
                    .getFirstChildWithName(new QName("Address"));
            String address=addressElement.getText();
            BrokerList.removeBrokerFromList(address);
            if(!BrokerList.isEmpty())
            {
                updateClients();
            }
            OMElement responseElement = factory.createOMElement("Response", null);
            responseElement.setText(addressElement.getText() + " removed successfully");
            responseEnvelop.getBody().addChild(responseElement);

            return responseEnvelop;
        }
        catch (NullPointerException ex)
        {
            logger.error("Error in processing received remove broker message", ex);
            return null;
        }
        catch (OMException ex)
        {
            logger.error("Error in processing received remove broker message", ex);
            return null;
        }
    }

     private void updateClients()
    {
         for(String client: ClientList.getClientList())
         {
            ArrayList<Broker> returnedBrokerSubList= BrokerList.shuffleAndReturnBrokerList();
            SOAPEnvelope updateClientEnvelope=createUpdateClientEnvelope(returnedBrokerSubList);
            try
            {
                ServiceClient serviceClient = new ServiceClient();
                //creating message context
                MessageContext outMsgCtx = new MessageContext();
                Options opts = outMsgCtx.getOptions();

                opts.setTo(new EndpointReference(client));
                opts.setAction(WihidumConstants.Operations.Update_Client);

                OperationClient opClient = serviceClient.createClient(ServiceClient.ANON_OUT_ONLY_OP);//ANON_OUT_IN_OP);

                outMsgCtx.setEnvelope(updateClientEnvelope);
                opClient.addMessageContext(outMsgCtx);
                opClient.execute(true);

                logger.info("Updates of broker lists is sent to "+client);

             }
        catch (NullPointerException ex)
        {
            ex.printStackTrace();
        }
        catch (AxisFault axisFault)
        {

        }
      }


    }
    private SOAPEnvelope createUpdateClientEnvelope(ArrayList<Broker> returnedBrokerList)
    {
        SOAPFactory factory= OMAbstractFactory.getSOAP12Factory();
        SOAPEnvelope updateEnvelope=factory.getDefaultEnvelope();

        OMNamespace wihidumNS=factory.createOMNamespace(WSEventingConstants.WIHIDUM_NAMESPACE,WSEventingConstants.WHIDUM_NAMESPACE_PREFIX);
        updateEnvelope.declareNamespace(wihidumNS);

        OMElement responseElement=factory.createOMElement(WSEventingConstants.ElementNames.Update_Client,wihidumNS);
        OMElement brokerListElement=factory.createOMElement(WSEventingConstants.ElementNames.BrokerList,wihidumNS);
        brokerListElement.setText("List of Brokers");
        responseElement.addChild(brokerListElement);

        for(Broker broker:returnedBrokerList)
        {
           logger.info("Broker in returning envelope:"+broker.getAddress());
           OMElement brokerElement=factory.createOMElement(WSEventingConstants.ElementNames.Broker,wihidumNS);
           brokerElement.setText(broker.getAddress());

           brokerListElement.addChild(brokerElement);

        }
        SOAPBody responseBody=updateEnvelope.getBody();
        responseBody.addChild(responseElement);
        return updateEnvelope;  //To change body of im
    }
}

